package com.brillilab.service.logic.topics;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.common.utils.DateUtil;
import com.brillilab.common.utils.MyBeanUtils;
import com.brillilab.domain.enums.comments.CommentsClassifyEnum;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.experiment.ExperimentStateEnum;
import com.brillilab.domain.enums.lab.LabMemberEnum;
import com.brillilab.domain.enums.method.MethodTypeUseTypeEnum;
import com.brillilab.domain.enums.plans.PlanMemberRoleEnum;
import com.brillilab.domain.enums.team.TeamMemberStateEnum;
import com.brillilab.domain.enums.topic.ExperimentIconEnum;
import com.brillilab.domain.enums.topic.TopicStateEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.experiments.ExperimentProduce;
import com.brillilab.domain.po.experiments.ExperimentRelation;
import com.brillilab.domain.po.global.GlobalKit;
import com.brillilab.domain.po.kit.Kit;
import com.brillilab.domain.po.lab.LabMember;
import com.brillilab.domain.po.method.Method;
import com.brillilab.domain.po.method.MethodType;
import com.brillilab.domain.po.method.MethodTypeHide;
import com.brillilab.domain.po.plans.Plan;
import com.brillilab.domain.po.plans.PlanExperimentGroup;
import com.brillilab.domain.po.plans.PlanTargetGroup;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.domain.po.team.TeamMember;
import com.brillilab.domain.po.topics.Topic;
import com.brillilab.domain.po.topics.TopicDirection;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.po.topics.TopicMember;
import com.brillilab.domain.po.topics.TopicTarget;
import com.brillilab.domain.vo.experiments.ExperimentIconListVo;
import com.brillilab.domain.vo.experiments.ExperimentMethodListVo;
import com.brillilab.domain.vo.lab.MemberInfoVo;
import com.brillilab.domain.vo.method.MethodDetail;
import com.brillilab.domain.vo.method.MethodVersionListItem;
import com.brillilab.domain.vo.plans.PlanMemberRoleVo;
import com.brillilab.domain.vo.team.TeamMemberVo;
import com.brillilab.domain.vo.topics.ExperimentDateListVo;
import com.brillilab.domain.vo.topics.ExperimentIconVo;
import com.brillilab.domain.vo.topics.ProduceVo;
import com.brillilab.domain.vo.topics.TopicAddFileVo;
import com.brillilab.domain.vo.topics.TopicAddReturnVo;
import com.brillilab.domain.vo.topics.TopicAddVo;
import com.brillilab.domain.vo.topics.TopicDirectionListVo;
import com.brillilab.domain.vo.topics.TopicDirectionsVo;
import com.brillilab.domain.vo.topics.TopicEditVo;
import com.brillilab.domain.vo.topics.TopicExperimentAddVo;
import com.brillilab.domain.vo.topics.TopicExperimentListAddVo;
import com.brillilab.domain.vo.topics.TopicExperimentResultVo;
import com.brillilab.domain.vo.topics.TopicExperimentVo;
import com.brillilab.domain.vo.topics.TopicExperimentsVo;
import com.brillilab.domain.vo.topics.TopicFileVo;
import com.brillilab.domain.vo.topics.TopicInfoVo;
import com.brillilab.domain.vo.topics.TopicListVo;
import com.brillilab.domain.vo.topics.TopicMemberVo;
import com.brillilab.domain.vo.topics.TopicNameVo;
import com.brillilab.domain.vo.topics.TopicRecycleBinVo;
import com.brillilab.domain.vo.topics.TopicSearchVo;
import com.brillilab.domain.vo.topics.TopicTargetListVo;
import com.brillilab.domain.vo.topics.TopicTargetPlanDateListVo;
import com.brillilab.domain.vo.topics.TopicTargetPlanDateVo;
import com.brillilab.domain.vo.topics.TopicTargetThumbnailVo;
import com.brillilab.domain.vo.topics.TopicTargetsVo;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.comments.ICommentsService;
import com.brillilab.service.core.experiments.IExperimentCommentService;
import com.brillilab.service.core.experiments.IExperimentProduceService;
import com.brillilab.service.core.experiments.IExperimentRelationService;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.global.IGlobalKitService;
import com.brillilab.service.core.kit.IKitService;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.method.IMethodService;
import com.brillilab.service.core.method.IMethodTypeHideService;
import com.brillilab.service.core.method.IMethodTypeService;
import com.brillilab.service.core.method.IMethodTypeUseService;
import com.brillilab.service.core.plans.IPlanExperimentGroupService;
import com.brillilab.service.core.plans.IPlanService;
import com.brillilab.service.core.plans.IPlanTargetGroupService;
import com.brillilab.service.core.system.IFileManageService;
import com.brillilab.service.core.team.ITeamMemberService;
import com.brillilab.service.core.team.ITeamService;
import com.brillilab.service.core.topics.ITopicDirectionService;
import com.brillilab.service.core.topics.ITopicExperimentService;
import com.brillilab.service.core.topics.ITopicMemberService;
import com.brillilab.service.core.topics.ITopicService;
import com.brillilab.service.core.topics.ITopicTargetService;
import com.brillilab.service.logic.method.MethodLogic;
import com.brillilab.service.logic.plans.PlanLogic;
import com.brillilab.service.logic.team.TeamLogic;
import com.brillilab.service.utils.NumberToLetterUtil;
import com.google.common.collect.Lists;

import cn.hutool.core.collection.CollUtil;

@Service
@Transactional
public class TopicLogic {

	@Resource
	private ILabMemberService labMemberService;
	@Resource
	private TeamLogic teamLogic;
	@Resource
	private ITeamMemberService teamMemberService;
	@Resource
	private ITopicService topicService;
	@Resource
	private IExperimentService experimentService;
	@Resource
	private ITopicDirectionService topicDirectionService;
	@Resource
	private ITopicTargetService topicTargetService;
	@Resource
	private IExperimentProduceService experimentProduceService;

	@Resource
	private IFileManageService fileManageService;
	@Resource
	private ITopicMemberService topicMemberService;
	@Resource
	private ITopicExperimentService topicExperimentService;
	@Resource
	private IPlanTargetGroupService planTargetGroupService;
	@Resource
	private IPlanExperimentGroupService planExperimentGroupService;
	@Resource
	private IPlanService planService;
	@Resource
	private IExperimentRelationService experimentRelationService;
	@Resource
	private IExperimentCommentService experimentCommentService;
	@Resource
	private IMethodService methodService;
	@Resource
	private IMethodTypeService methodTypeService;
	@Resource
	private MethodLogic methodLogic;
	@Resource
	private IKitService kitService;
	@Resource
	private PlanLogic planLogic;
	@Resource
	private IMethodTypeHideService methodTypeHideService;
	@Resource
	private ITeamService teamService;
	@Resource
	private IMethodTypeUseService methodTypeUseService;
	@Resource
	private ICommentsService commentsService;
	@Resource
	private IGlobalKitService globalKitService;

	/**
	 * 课题编辑权限：主执行人/主执行人的组长/PI
	 *
	 * @param topic
	 * @param userInfo
	 * @return
	 */
	public boolean topicEditPower(Topic topic, UserInfoVo userInfo) {
		Assert.notNull(topic, "课题不存在");
		Assert.isTrue(topic.getLabId().equals(userInfo.getLabId()), "课题不属于当前实验室!");
		if (topic.getExecutorId().equals(userInfo.getLabMemberId())) {
			return true;
		}

		if (userInfo.getIsOwner()) {
			return true;
		}

		TeamMemberVo leader = teamLogic.getLeaderOfTeamMember(topic.getLabId(), topic.getExecutorId());
		if (leader != null && leader.getLabMemberId().equals(userInfo.getLabMemberId())) {
			return true;
		}
		return false;
	}

	public Map<String, List<MemberInfoVo>> topicScreenMemberList(Long labId, Long labMemberId, boolean isOwner) {
		Map<String, List<MemberInfoVo>> map = new HashMap<>();
		if (isOwner) {
			List<MemberInfoVo> list = labMemberService.selectMemberVoList(labId, null);
			Map<Integer, List<MemberInfoVo>> voMap = list.stream()
					.collect(Collectors.groupingBy(MemberInfoVo::getState));
			List<MemberInfoVo> currentMemberList = voMap.get(LabMemberEnum.State.STATE_IN.getValue());

			map.put("currentMemberList", this.topicMemberSort(labMemberId, currentMemberList));
			List<MemberInfoVo> historyMemberList = voMap.get(LabMemberEnum.State.STATE_OUT.getValue());
			map.put("historyMemberList", historyMemberList);
		} else {
			boolean isLeader = teamLogic.isLeaderOrPi(labId, labMemberId);
			if (isLeader) {
				TeamMember teamMember = teamMemberService.selectOneByLabIdAndLabMemberId(labId, labMemberId);
				List<TeamMember> teamList = teamMemberService.selectListByTeamIdAndState(teamMember.getTeamId(),
						TeamMemberStateEnum.IN.getState());
				List<Long> labMemberIds = teamList.stream().map(TeamMember::getLabMemberId)
						.collect(Collectors.toList());
				if (!CollectionUtils.isEmpty(labMemberIds)) {
					List<MemberInfoVo> currentMemberList = labMemberService.selectMemberVoListByIds(labMemberIds);
					map.put("currentMemberList", this.topicMemberSort(labMemberId, currentMemberList));
				}
			}
		}
		return map;
	}

	private List<MemberInfoVo> topicMemberSort(Long labMemberId, List<MemberInfoVo> memberList) {
		List<MemberInfoVo> memberVoList = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(memberList)) {
			for (MemberInfoVo infoVo : memberList) {
				if (infoVo.getLabMemberId().equals(labMemberId)) {
					memberVoList.add(0, infoVo);
				} else {
					memberVoList.add(infoVo);
				}
			}
		}
		return memberVoList;
	}

	public PageVo<TopicListVo> getIndexTopicList(TopicSearchVo searcVo, UserInfoVo userInfo) {
		List<Long> memberIds = new ArrayList<Long>();
		if (searcVo.getLabMemberId() == null) {
			if (searcVo.isOwner()) {
				memberIds = labMemberService.selectMemberIds(searcVo.getLabId(),
						LabMemberEnum.State.STATE_IN.getValue());
			} else {
				memberIds.add(userInfo.getLabMemberId());
				boolean isLeader = teamLogic.isLeaderOrPi(searcVo.getLabId(), userInfo.getLabMemberId());
				if (isLeader) {
					TeamMember teamMember = teamMemberService.selectOneByLabIdAndLabMemberId(searcVo.getLabId(),
							userInfo.getLabMemberId());
					List<TeamMember> teamList = teamMemberService.selectListByTeamIdAndState(teamMember.getTeamId(),
							TeamMemberStateEnum.IN.getState());
					memberIds = teamList.stream().map(TeamMember::getLabMemberId).collect(Collectors.toList());
				}
			}
		} else {
			memberIds.add(searcVo.getLabMemberId());
		}

		PageVo<TopicListVo> pageVo = topicService.getIndexTopicList(searcVo.getLabId(), memberIds, searcVo.getState(),
				searcVo.getPageNum(), searcVo.getPageSize());
		List<TopicListVo> content = pageVo.getContent();
		if (CollectionUtils.isNotEmpty(content)) {
			content.forEach(vo -> {
				Topic topic = topicService.selectById(vo.getTopicId());
				boolean isPower = this.topicEditPower(topic, userInfo);
				vo.setIsEditPower(isPower ? 1 : 0);
			});
		}
		return pageVo;
	}

	/**
	 * 新建课题
	 *
	 * @author WuMenghao
	 * @param addVo
	 * @param userInfo
	 * @return
	 */
	public TopicAddReturnVo createNewTopic(TopicAddVo addVo, UserInfoVo userInfo) {

		// 基本信息
		TopicAddReturnVo vo = new TopicAddReturnVo();
		Topic topic = new Topic();
		topic.setLabId(userInfo.getLabId());
		topic.setName(addVo.getName());
		topic.setFundsCard(addVo.getFundsCard());
		String fileSecretKey = UUID.randomUUID().toString().replace("-", "").substring(16);
		topic.setFileSecretKey(fileSecretKey);
		topic.setFundsFrom(addVo.getFundsFrom());
		topic.setFunds(addVo.getFunds());
		topic.setStartTime(addVo.getStartTime());
		topic.setExecutorId(addVo.getExecutorId());
		topicService.insert(topic);

		List<TopicMember> insertList = new ArrayList<>();

		TopicMember executor = new TopicMember();
		executor.setLabId(userInfo.getLabId());
		executor.setTopicId(topic.getId());
		executor.setLabMemberId(addVo.getExecutorId());
		executor.setIsExecutor(BoolEnum.TRUE.getValue());
		executor.setState(BoolEnum.TRUE.getValue());
		insertList.add(executor);

		if (CollectionUtils.isNotEmpty(addVo.getLabMemberIds())) {// 成员
			// 去重
			List<Long> labMemberIds = addVo.getLabMemberIds().stream().distinct().collect(Collectors.toList());
			for (Long labMemberId : labMemberIds) {
				if (!labMemberId.equals(addVo.getExecutorId())) {
					TopicMember member = new TopicMember();
					member.setLabId(userInfo.getLabId());
					member.setTopicId(topic.getId());
					member.setLabMemberId(labMemberId);
					member.setIsExecutor(BoolEnum.FALSE.getValue());
					member.setState(BoolEnum.TRUE.getValue());
					insertList.add(member);
				}
			}
		}
		if (CollectionUtils.isNotEmpty(insertList))
			topicMemberService.insertBatch(insertList);

		// 文件
		List<FileManage> fileManageList = new ArrayList<FileManage>();
		if (org.apache.commons.collections.CollectionUtils.isNotEmpty(addVo.getTopicFileList())) {
			List<TopicAddFileVo> fileList = addVo.getTopicFileList();
			fileList.forEach(e -> Assert.isTrue(e.getFileClassify() != null, "file type can not be null"));
			fileList.forEach(fileVo -> {
				if (ArrayUtils.isNotEmpty(fileVo.getFileIds())) {
					// 直传
					fileManageService.relevanceBatch(fileVo.getFileIds(), topic.getId(),
							OssFileEnum.getEnum(fileVo.getFileClassify()), addVo.getLabId(), userInfo.getId());
				}
				if (CollectionUtils.isNotEmpty(fileVo.getFileList())) {
					// 续传
					List<FileManage> insertFileList = fileVo.getFileList().stream().filter(e -> e.getId() == null)
							.collect(Collectors.toList());

					List<FileManage> analyzeList = fileManageService.insertBatch(insertFileList, topic.getId(),
							OssFileEnum.getEnum(fileVo.getFileClassify()), addVo.getLabId(), userInfo.getId());
					fileManageList.addAll(analyzeList);
				}
			});
		}

		vo.setTopicId(topic.getId());
		vo.setFileList(fileManageList);
		return vo;
	}

	/**
	 * 可选课题主执行人（PI获取全部成员，组长获取研究小组组员）
	 *
	 * @param labId
	 * @param labMemberId
	 * @param isOwner
	 * @return
	 */
	public List<MemberInfoVo> getOptionalExecutorList(Long labId, Long labMemberId, boolean isOwner) {
		List<MemberInfoVo> list = new ArrayList<MemberInfoVo>();
		if (isOwner) {
			list = labMemberService.selectMemberVoList(labId, LabMemberEnum.State.STATE_IN.getValue());
		} else {
			List<Long> memberIds = new ArrayList<Long>();
			boolean isLeader = teamLogic.isLeaderOrPi(labId, labMemberId);
			if (isLeader) {
				TeamMember teamMember = teamMemberService.selectOneByLabIdAndLabMemberId(labId, labMemberId);
				List<TeamMember> teamList = teamMemberService.selectListByTeamIdAndState(teamMember.getTeamId(),
						TeamMemberStateEnum.IN.getState());
				memberIds = teamList.stream().map(TeamMember::getLabMemberId).collect(Collectors.toList());
			}
			memberIds.add(labMemberId);
			list = labMemberService.selectMemberVoListByIds(memberIds);
		}
		return this.topicMemberSort(labMemberId, list);
	}

	/**
	 * 课题列表成员列表
	 *
	 * @author WuMenghao
	 * @param topicId
	 * @param state
	 * @param labId
	 * @return
	 */
	public List<TopicMemberVo> getTopicMemberList(Long topicId, Integer state, Long labId, Long labMemberId) {
		return topicMemberService.selectVoList(labId, topicId, state);
	}

	/**
	 * 可选课题成员
	 *
	 * @author WuMenghao
	 * @param executorId
	 * @param labId
	 * @return
	 */
	public List<MemberInfoVo> getOptionalMemberList(Long executorId, Long labId) {
		List<MemberInfoVo> memberList = new ArrayList<MemberInfoVo>();
		List<Long> memberIds = teamService.getTeamLabMemberIds(executorId);
		if (CollectionUtils.isNotEmpty(memberIds)) {
			memberList = labMemberService.selectMemberVoListByIds(memberIds);
			if (CollectionUtils.isNotEmpty(memberList)) {
				for (Iterator<MemberInfoVo> iterator = memberList.iterator(); iterator.hasNext();) {
					MemberInfoVo vo = iterator.next();
					if (vo.getLabMemberId().equals(executorId)) {
						iterator.remove();
						break;
					}
				}
			}
		}
		return memberList;
	}

	/**
	 * 课题信息
	 *
	 * @param topicId
	 * @param labId
	 * @param labMemberId
	 * @return
	 */
	public TopicInfoVo getTopicInfo(Long topicId, Long labId, Long labMemberId) {
		Topic topic = topicService.selectById(topicId);
		Assert.isTrue(topic != null && topic.getIsDelete().equals(BoolEnum.FALSE.getValue()), "课题不存在!");
		Assert.isTrue(topic.getLabId().equals(labId), "课题不属于当前实验室!");

		// 主执行人 成员
		List<TopicMemberVo> topicMemberVos = topicMemberService.selectVoList(labId, topicId, null);
		TopicMemberVo executor = topicMemberVos.stream().filter(e -> e.getIsExecutor().equals(BoolEnum.TRUE.getValue()))
				.findFirst().orElse(null);
		Assert.notNull(executor, "主执行人不存在!");
		List<TopicMemberVo> members = topicMemberVos.stream()
				.filter(e -> e.getIsExecutor().equals(BoolEnum.FALSE.getValue())).collect(Collectors.toList());

		TopicInfoVo topicInfoVo = MyBeanUtils.copyBean(topic, TopicInfoVo.class);
		topicInfoVo.setExecutorImageUrl(executor.getImageUrl());
		topicInfoVo.setExecutorName(executor.getName());
		topicInfoVo.setDuty(executor.getDuty());
		topicInfoVo.setMemberList(members.stream().map(e -> {
			MemberInfoVo memberInfoVo = MyBeanUtils.copyBean(e, MemberInfoVo.class);
			memberInfoVo.setUserName(e.getName());
			return memberInfoVo;
		}).collect(Collectors.toList()));
		List<TopicFileVo> topicFileList = topicService.getTopicFileList(labId, topicId);
		topicInfoVo.setTopicFileList(topicFileList);

		return topicInfoVo;
	}

	public void topicExperimentAdd(TopicExperimentListAddVo addVo, UserInfoVo userInfo) {
		if (addVo != null && !CollectionUtils.isEmpty(addVo.getMethodList())) {
			List<TopicExperiment> list = topicExperimentService.getAllTopicExperimentList(addVo.getTargetId());

			List<TopicExperiment> noCheckTotalList = list.stream()
					.filter(s -> BoolEnum.FALSE.getValue().equals(s.getIsCheck())).collect(Collectors.toList());
			List<TopicExperiment> checkTotalList = list.stream()
					.filter(s -> BoolEnum.TRUE.getValue().equals(s.getIsCheck())).collect(Collectors.toList());

			List<TopicExperiment> noCheckList = noCheckTotalList.stream()
					.filter(s -> BoolEnum.FALSE.getValue().equals(s.getIsDelete())).collect(Collectors.toList());
			List<TopicExperiment> checkList = checkTotalList.stream()
					.filter(s -> BoolEnum.FALSE.getValue().equals(s.getIsDelete())).collect(Collectors.toList());

			Map<Long, List<TopicExperimentAddVo>> map = addVo.getMethodList().stream()
					.collect(Collectors.groupingBy(TopicExperimentAddVo::getFirstTypeId));
			if (CollectionUtils.isNotEmpty(map.get(2L))) {
				int noCheckNum = map.get(2L).size() + noCheckList.size();
				Assert.isTrue(noCheckNum <= 10, "制备实验最多只能10个");
			}
			if (CollectionUtils.isNotEmpty(map.get(1L))) {
				int checkNum = map.get(1L).size() + checkList.size();
				Assert.isTrue(checkNum <= 6, "检测实验最多只能6个");
			}
			int noCheckTotalNum = noCheckTotalList.size();
			int checkTotalNum = checkTotalList.size();

			List<TopicExperiment> noDeleList = list.stream()
					.filter(s -> BoolEnum.FALSE.getValue().equals(s.getIsDelete())).collect(Collectors.toList());
			Map<Long, List<TopicExperiment>> noDeleMap = noDeleList.stream()
					.collect(Collectors.groupingBy(TopicExperiment::getMethodTypeId));


			List<Long> addMethodTypeIds = new ArrayList<>();
			for (TopicExperimentAddVo method : addVo.getMethodList()) {
				Assert.isTrue(CollectionUtils.isEmpty(noDeleMap.get(method.getMethodTypeId())),
						"已存在" + method.getMethodTypeName() + "类型实验");

				TopicExperiment topicExperiment = new TopicExperiment();
				topicExperiment.setLabId(addVo.getLabId());
				topicExperiment.setTopicId(addVo.getTopicId());
				topicExperiment.setTopicDirectionId(addVo.getDirectionId());
				topicExperiment.setTopicTargetId(addVo.getTargetId());
				topicExperiment.setExecutorId(addVo.getExecutorId());

				if (method.getFirstTypeId() == 1) {
					checkTotalNum = checkTotalNum + 1;
					topicExperiment.setSerial(NumberToLetterUtil.numberToLetter(checkTotalNum));
					topicExperiment.setIsCheck(BoolEnum.TRUE.getValue());
				} else {
					noCheckTotalNum = noCheckTotalNum + 1;
					topicExperiment.setSerial(String.valueOf(noCheckTotalNum));
				}

				topicExperiment.setFirstTypeId(method.getFirstTypeId());
				topicExperiment.setMethodTypeId(method.getMethodTypeId());

				topicExperiment.setMethodTypeName(method.getMethodTypeName());

				topicExperiment.setMethodId(method.getMethodId());
				topicExperiment = topicExperimentService.insert(topicExperiment);
				experimentService.experimentAdd(topicExperiment);

				addMethodTypeIds.add(method.getMethodTypeId());
			}

			if (addMethodTypeIds.size() > 0) {
				methodTypeUseService.insertOrUpdateThirdMethodTypeUseBatch(addMethodTypeIds, userInfo.getId(),
						MethodTypeUseTypeEnum.ADD_EXPERIMENT);
			}
		}
	}

	/**
	 * 结束课题
	 * 
	 * @author WuMenghao
	 * @param topic
	 * @param userInfo
	 */
	public void endTopic(Topic topic, UserInfoVo userInfo) {
		topic.setEndTime(new Date());
		topic.setState(TopicStateEnum.COMPLETE.getValue());
		topicService.update(topic);

		planTargetGroupService.endGroupByTopicId(topic.getId());
	}

	/**
	 * 编辑课题
	 * 
	 * @param editVo
	 * @param userInfo
	 * @return
	 */
	public TopicAddReturnVo editTopic(TopicEditVo editVo, UserInfoVo userInfo) {
		Topic topic = topicService.selectById(editVo.getId());
		boolean isPower = this.topicEditPower(topic, userInfo);

		Assert.isTrue(isPower, "你没有权限编辑该课题");
		topic.setId(editVo.getId());
		topic.setExecutorId(editVo.getExecutorId());
		topic.setName(editVo.getName());
		topic.setFunds(editVo.getFunds() != null ? editVo.getFunds() : "");
		topic.setFundsFrom(editVo.getFundsFrom() != null ? editVo.getFundsFrom() : "");
		topic.setFundsCard(editVo.getFundsCard() != null ? editVo.getFundsCard() : "");
		topic.setStartTime(editVo.getStartTime());
		topicService.update(topic);

		if (editVo.getExecutorId() != null) {
			TopicMember mainMember = topicMemberService.getTopicMainMember(topic.getId());
			if (mainMember == null) {
				mainMember = new TopicMember();
				mainMember.setLabId(topic.getLabId());
				mainMember.setTopicId(topic.getId());
				mainMember.setLabMemberId(editVo.getExecutorId());
				mainMember.setIsExecutor(BoolEnum.TRUE.getValue());
				mainMember.setState(BoolEnum.TRUE.getValue());
				topicMemberService.insertBatch(CollUtil.toList(mainMember));
			} else if (!mainMember.getLabMemberId().equals(editVo.getExecutorId())) {
				mainMember.setLabMemberId(editVo.getExecutorId());
				topicMemberService.updateById(mainMember);
			}
		}

		// 课题成员
		List<TopicMember> insertList = new ArrayList<>(0);
		topicMemberService.deleteMembers(topic.getId());
		if (CollectionUtils.isNotEmpty(editVo.getLabMemberIds())) {// 成员
			// 去重
			List<Long> labMemberIds = editVo.getLabMemberIds().stream().distinct().collect(Collectors.toList());
			for (Long labMemberId : labMemberIds) {
				if (!labMemberId.equals(topic.getExecutorId())) {
					TopicMember member = new TopicMember();
					member.setLabId(topic.getLabId());
					member.setTopicId(topic.getId());
					member.setLabMemberId(labMemberId);
					member.setIsExecutor(BoolEnum.FALSE.getValue());
					member.setState(BoolEnum.TRUE.getValue());
					insertList.add(member);
				}
			}
		}
		if (CollectionUtils.isNotEmpty(insertList))
			topicMemberService.insertBatch(insertList);

		// 文件
		List<FileManage> fileManageList = new ArrayList<FileManage>();
		if (CollectionUtils.isNotEmpty(editVo.getTopicFileList())) {
			List<TopicAddFileVo> fileList = editVo.getTopicFileList();
			fileList.forEach(e -> Assert.isTrue(e.getFileClassify() != null, "file type can not be null"));
			fileList.forEach(fileVo -> {
				if (ArrayUtils.isNotEmpty(fileVo.getFileIds())) {
					// 直传
					fileManageService.relevanceBatch(fileVo.getFileIds(), topic.getId(),
							OssFileEnum.getEnum(fileVo.getFileClassify()), userInfo.getLabId(), userInfo.getId());
				}
				if (CollectionUtils.isNotEmpty(fileVo.getFileList())) {
					// 续传
					List<FileManage> analyzeList = fileManageService.insertBatch(fileVo.getFileList(), topic.getId(),
							OssFileEnum.getEnum(fileVo.getFileClassify()), userInfo.getLabId(), userInfo.getId());
					fileManageList.addAll(analyzeList);
				}
			});
		}

		TopicAddReturnVo vo = new TopicAddReturnVo();
		vo.setTopicId(topic.getId());
		vo.setFileList(fileManageList);
		return vo;
	}

	/** WuMenghao */
	/**
	 * 判断当前用户是否是课题成员
	 * 
	 * @param labMemberId
	 * @return
	 */
	public boolean isTopicMember(Long topicId, Long labMemberId) {
		List<TopicMember> topicMembers = topicMemberService.selectListByTopicId(topicId);
		if (CollectionUtils.isNotEmpty(topicMembers)) {
			List<Long> topicLabMemberIds = topicMembers.stream().map(TopicMember::getLabMemberId).distinct()
					.collect(Collectors.toList());
			return topicLabMemberIds.contains(labMemberId);
		}
		return false;
	}

	/**
	 * 判断当前用户是否可以新增研究内容/实验流/实验目标
	 * 
	 * @author WuMenghao
	 * @param userInfo
	 * @return
	 */
	public boolean topicDirectionCanAdd(Long topicId, UserInfoVo userInfo) {
		Topic topic = topicService.selectById(topicId);
		Assert.notNull(topic, "课题不存在!");
		Assert.isTrue(topic.getLabId().equals(userInfo.getLabId()), "课题不属于该实验室!");

		List<TopicMember> topicMembers = topicMemberService.selectListByTopicId(topicId);
		List<Long> tmLabMemberIds = topicMembers.stream().map(TopicMember::getLabMemberId).distinct()
				.collect(Collectors.toList());

		TeamMemberVo leader = teamLogic.getLeaderOfTeamMember(userInfo.getLabId(), userInfo.getLabMemberId());

		// pi
		if (userInfo.getIsOwner()) {
			return true;
		}
		// 主执行人
		if (userInfo.getLabMemberId().equals(topic.getExecutorId())) {
			return true;
		}
		// 成员
		if (tmLabMemberIds.contains(userInfo.getLabMemberId())) {
			return true;
		}

		// teamLeader
		if (leader != null) {
			if (leader.getLabMemberId().equals(userInfo.getLabMemberId())) {
				return true;
			}
		}

		return false;
	}

	/** end */

	/**
	 * 获取实验流列表
	 * 
	 * @param topicDirectionId
	 * @return
	 */
	public TopicTargetsVo getTargetList(Long topicDirectionId, UserInfoVo userInfo) {
		TopicTargetsVo targetsVo = new TopicTargetsVo();

		TopicDirection direction = topicDirectionService.getById(topicDirectionId);
		Topic topic = topicService.selectById(direction.getTopicId());
		boolean isPower = this.topicEditPower(topic, userInfo);
		boolean bool = isPower || this.isTopicMember(topic.getId(), userInfo.getLabMemberId());

		List<TopicTargetListVo> voList = new ArrayList<TopicTargetListVo>();
		List<TopicTarget> targetList = topicTargetService.getTargetList(topicDirectionId);
		if (CollectionUtils.isNotEmpty(targetList)) {
			for (TopicTarget topicTarget : targetList) {
				TopicTargetListVo vo = this.topicTargetToTopicTargetListVo(topicTarget);
				vo.setTopicName(topic.getName());
				vo.setTopicDirectionName(direction.getName());

				vo.setIsEditPower(isPower ? 1 : 0);
				vo.setTopicState(topic.getState());
				vo.setMainExecutorId(topic.getExecutorId());
				if (bool) {
					boolean isAddPlan = planService.isAddPlan(topicTarget.getId());
					if (isAddPlan) {
						vo.setIsAddPlan(BoolEnum.TRUE.getValue());
					}
				}
				voList.add(vo);
			}
		}
		targetsVo.setTopicId(topic.getId());
		targetsVo.setTopicName(topic.getName());
		targetsVo.setTopicDirectionId(direction.getId());
		targetsVo.setTopicDirectionName(direction.getName());
		targetsVo.setTopicDirectionFigure(direction.getFigure());
		targetsVo.setTargetList(voList);
		return targetsVo;
	}

	private TopicTargetListVo topicTargetToTopicTargetListVo(TopicTarget target) {
		TopicTargetListVo vo = new TopicTargetListVo();
		vo.setTopicId(target.getTopicId());
		vo.setTopicDirectionId(target.getTopicDirectionId());
		vo.setTopicTargetId(target.getId());
		vo.setFigure(target.getFigure());
		vo.setColor(target.getColor());
		vo.setName(target.getName());

		int topicExperimentNum = topicExperimentService.getCount(target.getId(), null, IsDeleteEnum.NO.getValue());
		vo.setTopicExperimentNum(topicExperimentNum);
		List<TopicExperimentResultVo> resultList = new ArrayList<TopicExperimentResultVo>();
		if (topicExperimentNum > 0) {
			List<TopicTargetPlanDateVo> planDateList = planTargetGroupService.getTargetPlanList(target.getId());
			vo.setPlanDateList(planDateList);
			Long targetGroupId = null;
			if (CollectionUtils.isNotEmpty(planDateList)) {
				TopicTargetPlanDateVo planDateVo = planDateList.get(0);
				targetGroupId = planDateVo.getTargetGroupId();
				vo.setIsHistory(planDateVo.getIsHistory());
			}
			resultList = this.getExperimentResultList(targetGroupId, target.getId());
		}
		vo.setExperimentResultList(resultList);
		return vo;
	}

	/**
	 * 获取实验流的不同计划日期实验结果
	 * 
	 * @param targetGroupId
	 * @return
	 */
	public List<TopicExperimentResultVo> getExperimentResultList(Long targetGroupId, Long targetId) {
		List<TopicExperimentResultVo> resultList = new ArrayList<TopicExperimentResultVo>();
		if (targetId == null) {
			PlanTargetGroup targetGroup = planTargetGroupService.getById(targetGroupId);
			targetId = targetGroup.getTopicTargetId();
		}

		List<TopicExperiment> topicExperimentList = topicExperimentService.getTopicExperimentList(targetId,
				BoolEnum.TRUE.getValue());

		if (CollectionUtils.isNotEmpty(topicExperimentList)) {
			Map<Long, List<Experiment>> map = new HashMap<Long, List<Experiment>>();
			if (targetGroupId != null) {
				List<Plan> planList = planService.getPlanListByTargetGroupId(targetGroupId);
				List<Long> experimentIds = planList.stream().map(Plan::getExperimentId).collect(Collectors.toList());
				List<Experiment> experimentList = experimentService.selectByIds(experimentIds);
				map = experimentList.stream().collect(Collectors.groupingBy(Experiment::getTopicExperimentId));
			}
			for (TopicExperiment topicExperiment : topicExperimentList) {
				TopicExperimentResultVo resultVo = new TopicExperimentResultVo();
				resultVo.setTopicExperimentId(topicExperiment.getId());
				resultVo.setIsPublish(topicExperiment.getIsPublish());
				resultVo.setMethodTypeName(topicExperiment.getMethodTypeName());
				resultVo.setExecutorId(topicExperiment.getExecutorId());
				resultVo.setState(TopicStateEnum.NOT_STARTED.getValue());
				List<Experiment> list = map.get(topicExperiment.getId());
				if (CollectionUtils.isNotEmpty(list)) {
					Experiment experiment = list.get(0);
					resultVo.setExperimentId(experiment.getId());
					resultVo.setIsExpect(experiment.getIsExpect());
					resultVo.setStartTime(experiment.getStartTime());
					resultVo.setState(experiment.getState());
					List<FileManage> compressAnalysisFile = fileManageService
							.selectList(OssFileEnum.AnalyzeDataFileThumbnail, experiment.getId());
					if (CollectionUtils.isNotEmpty(compressAnalysisFile)) {
						resultVo.setCompressAnalysisFile(compressAnalysisFile.get(0));
					}
				}
				resultList.add(resultVo);
			}
		}
		return resultList;
	}

	public List<TopicExperimentResultVo> getExperimentHistory(Long topicExperimentId) {
		List<TopicExperimentResultVo> historyList = experimentService.getExperimentHistory(topicExperimentId);
		List<Long> experimentIds = historyList.stream().map(TopicExperimentResultVo::getExperimentId).distinct()
				.collect(Collectors.toList());
		List<FileManage> analysisFiles = fileManageService.selectList(OssFileEnum.AnalyzeDataFile, experimentIds);
		List<FileManage> compresses = fileManageService.selectList(OssFileEnum.AnalyzeDataFileThumbnail, experimentIds);
		if (CollectionUtils.isNotEmpty(historyList)) {
			historyList.forEach(result -> {
				List<FileManage> analysisFile = analysisFiles.stream()
						.filter(e -> result.getExperimentId().equals(e.getReferDataId())).collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(analysisFile)) {
					result.setAnalysisFile(analysisFile.get(0));
				}
				List<FileManage> compress = compresses.stream()
						.filter(e -> result.getExperimentId().equals(e.getReferDataId())).collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(compress)) {
					result.setCompressAnalysisFile(compress.get(0));
				}
			});
		}
		return historyList;
	}

	public TopicTargetThumbnailVo getThumbnailList(Long topicDirectionId) {
		TopicTargetThumbnailVo thumbnailVo = new TopicTargetThumbnailVo();
		int count = topicTargetService.getCount(topicDirectionId, BoolEnum.FALSE.getValue());
		thumbnailVo.setIsMore(count > 6 ? 1 : 0);
		List<TopicTargetListVo> voList = new ArrayList<TopicTargetListVo>();
		if (count > 0) {
			List<TopicTarget> targetList = topicTargetService.getTargetList(topicDirectionId, 6);
			if (CollectionUtils.isNotEmpty(targetList)) {
				for (TopicTarget target : targetList) {
					voList.add(this.topicTargetToTopicTargetListVo(target));
				}
			}
		}
		thumbnailVo.setTargetList(voList);
		return thumbnailVo;
	}

	public TopicExperimentsVo getExperimentList(UserInfoVo userInfo, Long topicTargetId, Long targetGroupId) {

		Map<Long, List<Plan>> planMap = new HashMap<Long, List<Plan>>();
		Map<Long, List<PlanExperimentGroup>> experimentGroupMap = new HashMap<Long, List<PlanExperimentGroup>>();

		PlanTargetGroup group = null;
		if (targetGroupId != null) {
			group = planTargetGroupService.getById(targetGroupId);
		} else {
			group = planTargetGroupService.getNewestPlanTargetGroup(topicTargetId);
		}

		if (group != null) {
			List<Plan> planList = planService.getNewPlanList(group.getId());
			planMap = planList.stream().collect(Collectors.groupingBy(Plan::getTopicExperimentId));
			List<PlanExperimentGroup> experimentGroupList = planExperimentGroupService
					.getExperimentGroupList(group.getId());
			experimentGroupMap = experimentGroupList.stream()
					.collect(Collectors.groupingBy(PlanExperimentGroup::getTopicExperimentId));
		}

		TopicTarget target = topicTargetService.selectById(topicTargetId);
		TopicDirection direction = topicDirectionService.getById(target.getTopicDirectionId());
		Topic topic = topicService.selectById(target.getTopicId());

		boolean isEditPower = this.topicEditPower(topic, userInfo);

		List<TopicExperimentVo> experimentVoList = topicExperimentService.getTopicExperimentVoList(topicTargetId);

		if (CollectionUtils.isNotEmpty(experimentVoList)) {
			List<Experiment> experimentList = experimentService.getExperimentList(topicTargetId);
			Map<Long, List<Experiment>> experimentMap = experimentList.stream()
					.collect(Collectors.groupingBy(Experiment::getTopicExperimentId));
			for (TopicExperimentVo vo : experimentVoList) {
				if (isEditPower) {
					vo.setIsEditPower(BoolEnum.TRUE.getValue());
				}
				if (!TopicStateEnum.COMPLETE.getValue().equals(topic.getState()) && group != null
						&& TopicStateEnum.UNDER_WAY.getValue().equals(group.getState())) {
					PlanMemberRoleVo memberRole = planLogic.getMemberRole(userInfo, vo.getExecutorId());
					if (memberRole.getRole() != PlanMemberRoleEnum.ORDINARY.getValue()) {
						if (memberRole.getRole() == PlanMemberRoleEnum.MAIN_EXECUTORID.getValue()) {
							if (topic.getExecutorId().equals(userInfo.getLabMemberId())) {
								vo.setIsOperatePlan(BoolEnum.TRUE.getValue());
							}
						} else {
							vo.setIsOperatePlan(BoolEnum.TRUE.getValue());
						}
					}
				}

				if (userInfo.getLabMemberId().equals(topic.getExecutorId())
						|| userInfo.getLabMemberId().equals(vo.getExecutorId())) {
					vo.setOperateType(1);
					if (vo.getIsDelete().equals(IsDeleteEnum.NULLIFY.getValue())) {
						vo.setOperateType(3);
					} else if (BoolEnum.TRUE.getValue().equals(vo.getIsCheck())) {
						List<Experiment> list = experimentMap.get(vo.getTopicExperimentId());
						if (CollectionUtils.isNotEmpty(list)) {
							List<Long> experimentIds = list.stream().map(Experiment::getId)
									.collect(Collectors.toList());
							int count = fileManageService.selectCount(Arrays
									.asList(OssFileEnum.AnalyzeDataFile.getKey(), OssFileEnum.PrimaryDataFile.getKey()),
									experimentIds);
							if (count > 0)
								vo.setOperateType(2);
						}
					}
				}

				if (group != null) {
					targetGroupId = group.getId();
					vo.setTargetGroupState(group.getState());
					vo.setTargetGroupId(group.getId());
					List<Plan> list = planMap.get(vo.getTopicExperimentId());
					List<PlanExperimentGroup> list2 = experimentGroupMap.get(vo.getTopicExperimentId());
					if (CollectionUtils.isNotEmpty(list)) {
						Plan plan = list.get(0);
						vo.setExperimentId(plan.getExperimentId());
						vo.setExperimentGroupId(plan.getExperimentGroupId());
						vo.setPlanId(plan.getExperimentId());
					} else if (CollectionUtils.isNotEmpty(list2)) {
						vo.setExperimentGroupId(list2.get(0).getId());
					}
				}

			}
		}
		List<TopicExperimentVo> voList = setExperimentVoList(userInfo.getLabMemberId(), experimentVoList,
				targetGroupId);

		TopicExperimentsVo experimentsVo = new TopicExperimentsVo();
		experimentsVo.setTopicId(topic.getId());
		experimentsVo.setTopicName(topic.getName());
		experimentsVo.setTopicDirectionId(direction.getId());
		experimentsVo.setTopicDirectionName(direction.getName());
		experimentsVo.setTopicDirectionFigure(direction.getFigure());
		experimentsVo.setTopicTargetId(target.getId());
		experimentsVo.setTopicTargetName(target.getName());
		experimentsVo.setTopicTargetFigure(target.getFigure());
		experimentsVo.setColor(target.getColor());
		experimentsVo.setVoList(voList);
		return experimentsVo;
	}

	public List<TopicExperimentVo> setExperimentVoList(Long labMemberId, List<TopicExperimentVo> experimentVoList,
			Long targetGroupId) {

		if (CollectionUtils.isNotEmpty(experimentVoList)) {
			List<Long> experimentIds = experimentVoList.stream().filter(p -> p.getExperimentId() != null)
					.map(TopicExperimentVo::getExperimentId).collect(Collectors.toList());

			List<Experiment> experimentList = experimentService.selectByIds(experimentIds);
			Map<Long, List<Experiment>> experimentMap = experimentList.stream()
					.collect(Collectors.groupingBy(Experiment::getId));

			List<ExperimentIconListVo> listVo = experimentService.getExperimentIconVoList(experimentIds);
			Map<Long, List<ExperimentIconListVo>> iconMap = listVo.stream()
					.collect(Collectors.groupingBy(ExperimentIconListVo::getExperimentId));

			List<Long> topicExperimentIds = experimentVoList.stream().map(TopicExperimentVo::getTopicExperimentId)
					.collect(Collectors.toList());
			Map<Long, List<ExperimentDateListVo>> experimentDateMap = CollUtil.newHashMap();
			if (targetGroupId != null) {
				List<ExperimentDateListVo> experimentDateList = experimentService.getExperimentDateListVo(topicExperimentIds, targetGroupId);
				experimentDateMap = experimentDateList.stream().collect(Collectors.groupingBy(ExperimentDateListVo::getTopicExperimentId));
			}

			List<ExperimentRelation> relationList = experimentRelationService.getRelationList(experimentIds);
			Map<Long, List<ExperimentRelation>> relationMap = relationList.stream()
					.collect(Collectors.groupingBy(ExperimentRelation::getExperimentId));

			for (TopicExperimentVo experimentVo : experimentVoList) {
				int commentNum = commentsService.getCommentNum(CommentsClassifyEnum.EXPERIMENT.getValue(),experimentVo.getExperimentId(), null);
				experimentVo.setCommentNum(commentNum);

				List<ExperimentDateListVo> experimentDateList = experimentDateMap.get(experimentVo.getTopicExperimentId());
				if (CollUtil.isNotEmpty(experimentDateList)) {
					experimentVo.setExperimentList(experimentDateList);
				}

				if (experimentVo.getPlanId() != null) {
					if (BoolEnum.TRUE.getValue().equals(experimentVo.getIsCheck())) {
						int primaryDataNum = fileManageService.selectCount(
								Arrays.asList(OssFileEnum.PrimaryDataFile.getKey()),
								Arrays.asList(experimentVo.getExperimentId()));
						if (primaryDataNum > 0) {
							experimentVo.setIsPrimaryData(BoolEnum.TRUE.getValue());
						}

						List<FileManage> compressAnalysisFile = fileManageService
								.selectList(OssFileEnum.AnalyzeDataFileThumbnail, experimentVo.getExperimentId());
						if (CollectionUtils.isNotEmpty(compressAnalysisFile)) {
							experimentVo.setCompressAnalysisFile(compressAnalysisFile.get(0));
						}
					} else {
						PageVo<ExperimentProduce> pageVo = experimentProduceService
								.produceList(experimentVo.getExperimentId(), 1, 3);
						if (pageVo != null && CollectionUtils.isNotEmpty(pageVo.getContent())) {
							List<ProduceVo> produceList = Lists.newArrayList();
							for (ExperimentProduce produce : pageVo.getContent()) {
								produceList.add(new ProduceVo(produce.getReagentTypeId(), produce.getName()));
							}
							experimentVo.setProduceList(produceList);
						}
					}
					Experiment experiment = experimentMap.get(experimentVo.getExperimentId()).get(0);
					experimentVo.setState(experiment.getState());
					experimentVo.setIsAddGroup(experiment.getIsAddGroup());
					experimentVo.setIsAddAnalyze(experiment.getIsAddAnalyze());
					experimentVo.setIsAddTrouble(experiment.getIsAddTrouble());
					experimentVo.setRelationList(relationMap.get(experimentVo.getExperimentId()));
					ExperimentIconListVo iconVo = iconMap.get(experimentVo.getExperimentId()).get(0);
					experimentVo.setIconList(this.getExperimentIcon(labMemberId, iconVo, experimentVo));
				} else {
					experimentVo.setState(0);
					experimentVo.setStartType(null);
					ExperimentIconListVo iconVo = iconMap.get(experimentVo.getExperimentId()).get(0);
					experimentVo.setIconList(this.getExperimentIcon(labMemberId, iconVo, experimentVo));
				}
			}
		}
		return experimentVoList;
	}

	public List<ExperimentIconVo> experimentIcon(Long labMemberId, Long experimentId) {
		Experiment experiment = experimentService.selectById(experimentId);
		List<ExperimentIconListVo> listVo = experimentService
				.getExperimentIconVoList(Arrays.asList(experiment.getId()));
		TopicExperimentVo topicExperimentVo = new TopicExperimentVo();
		topicExperimentVo.setIsCheck(experiment.getIsCheck());
		topicExperimentVo.setIsAddAnalyze(experiment.getIsAddAnalyze());
		topicExperimentVo.setIsAddGroup(experiment.getIsAddGroup());
		topicExperimentVo.setIsAddTrouble(experiment.getIsAddTrouble());
		return this.getExperimentIcon(labMemberId, listVo.get(0), topicExperimentVo);
	}

	private List<ExperimentIconVo> getExperimentIcon(Long labMemberId, ExperimentIconListVo iconVo,
			TopicExperimentVo topicExperimentVo) {

		List<ExperimentIconVo> iconList = new ArrayList<ExperimentIconVo>();
		iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_1, iconVo.getIsGroup(),
				!labMemberId.equals(topicExperimentVo.getExecutorId()) && topicExperimentVo.getIsAddGroup() == 1 ? 1
						: 0));
		iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_2, iconVo.getIsBill(), 0));
		iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_3, iconVo.getIsContent(), 0));
		if (iconVo.getIsExpect() != null) {
			iconList.add(new ExperimentIconVo(
					iconVo.getIsExpect() == 1 ? ExperimentIconEnum.ICON_4 : ExperimentIconEnum.ICON_5, 1, 0));
		} else {
			iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_4, 0, 0));
		}

		if (topicExperimentVo.getIsCheck() == 1) {
			iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_8, iconVo.getIsAnalyze(),
					!labMemberId.equals(topicExperimentVo.getExecutorId()) && topicExperimentVo.getIsAddAnalyze() == 1
							? 1
							: 0));
			iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_7, iconVo.getIsTrouble(),
					!labMemberId.equals(topicExperimentVo.getExecutorId()) && topicExperimentVo.getIsAddTrouble() == 1
							? 1
							: 0));
			iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_9, iconVo.getIsPrimary(), 0));
//			BOSS要求暂时屏蔽
//			iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_10, iconVo.getIsPPT(), 0));
		} else {
			iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_6, iconVo.getIsProduce(), 0));
			iconList.add(new ExperimentIconVo(ExperimentIconEnum.ICON_7, iconVo.getIsTrouble(),
					!labMemberId.equals(topicExperimentVo.getExecutorId()) && topicExperimentVo.getIsAddTrouble() == 1 ? 1 : 0));
		}
		return iconList;
	}


	public TopicTargetPlanDateListVo getTargetPlanDateList(Long labMemberId, Long topicTargetId) {
		TopicTarget target = topicTargetService.selectById(topicTargetId);
		Topic topic = topicService.selectById(target.getTopicId());
		TopicTargetPlanDateListVo vo = new TopicTargetPlanDateListVo();
		vo.setTopicId(target.getTopicId());
		vo.setTopicState(topic.getState());
		vo.setTopicDirectionId(target.getTopicDirectionId());
		vo.setTopicTargetId(target.getId());
		vo.setFigure(target.getFigure());
		vo.setColor(target.getColor());
		vo.setName(target.getName());
		vo.setMainExecutorId(topic.getExecutorId());
		boolean isTopicMember = this.isTopicMember(target.getTopicId(), labMemberId);
		vo.setIsTopicMember(isTopicMember ? BoolEnum.TRUE.getValue() : BoolEnum.FALSE.getValue());

		if (topic.getExecutorId().equals(labMemberId)) {
			List<Topic> topicList = topicService.getTopicByMainExecutorId(labMemberId);
			if (CollectionUtils.isNotEmpty(topicList) && topicList.size() == 0) {
				int count = topicExperimentService.getCount(topic.getId());
				vo.setIsHistoryTips(count == 0 ? BoolEnum.TRUE.getValue() : BoolEnum.FALSE.getValue());
			}

		}
		List<TopicTargetPlanDateVo> planDateList = planTargetGroupService.getTargetPlanList(target.getId());
		vo.setPlanDateList(planDateList);
		if (CollectionUtils.isNotEmpty(planDateList)) {
			TopicTargetPlanDateVo dateVo = planDateList.get(0);
			if (TopicStateEnum.UNDER_WAY.getValue().equals(dateVo.getState())
					&& BoolEnum.TRUE.getValue().equals(dateVo.getIsHistory())) {
				vo.setIsHistory(BoolEnum.TRUE.getValue());
			}
		}
		if (labMemberId.equals(topic.getExecutorId()) && BoolEnum.FALSE.getValue().equals(vo.getIsHistory())) {
			List<TopicExperiment> list = topicExperimentService.getTopicExperimentList(topicTargetId);
			if (CollectionUtils.isNotEmpty(list)) {
				boolean isAddPlan = planService.isAddPlan(topicTargetId);
				if (isAddPlan) {
					vo.setIsShowAddButton(BoolEnum.TRUE.getValue());
				}
			}
		}
		return vo;
	}

	public TopicExperimentVo getExperimentInfo(UserInfoVo userInfo, Long experimentId) {

		Experiment experiment = experimentService.selectById(experimentId);
		Topic topic = topicService.selectById(experiment.getTopicId());

		TopicExperimentVo vo = topicExperimentService.getTopicExperimentVo(experiment.getTopicExperimentId());
		if (vo != null) {
			TopicTarget target = topicTargetService.selectById(experiment.getTopicTargetId());
			vo.setColor(target.getColor());

			boolean isEditPower = this.topicEditPower(topic, userInfo);
			vo.setIsEditPower(isEditPower ? BoolEnum.TRUE.getValue() : BoolEnum.FALSE.getValue());

			PlanTargetGroup targetGroup = null;
			Plan plan = planService.getPlanByExperimentId(experimentId);
			if (plan != null) {
				vo.setExperimentId(plan.getExperimentId());
				vo.setTargetGroupId(plan.getTargetGroupId());
				vo.setExperimentGroupId(plan.getExperimentGroupId());
				vo.setPlanId(plan.getId());
				targetGroup = planTargetGroupService.getById(plan.getTargetGroupId());
				vo.setTargetGroupState(targetGroup.getState());
			} else if(experimentId.equals(vo.getExperimentId())){
				targetGroup = planTargetGroupService.getNewestPlanTargetGroup(vo.getTopicTargetId());
				if (targetGroup != null) {
					vo.setTargetGroupId(targetGroup.getId());
					vo.setTargetGroupState(targetGroup.getState());
					PlanExperimentGroup experimentGroup = planExperimentGroupService.getExperimentGroup(targetGroup.getId(), vo.getTopicExperimentId());
					if (experimentGroup != null) {
						vo.setExperimentGroupId(experimentGroup.getId());
					}
				}
			}

			if (!TopicStateEnum.COMPLETE.getValue().equals(topic.getState()) && targetGroup != null
					&& TopicStateEnum.UNDER_WAY.getValue().equals(targetGroup.getState())) {
				PlanMemberRoleVo memberRole = planLogic.getMemberRole(userInfo, vo.getExecutorId());
				if (memberRole.getRole() != PlanMemberRoleEnum.ORDINARY.getValue()) {
					if (memberRole.getRole() == PlanMemberRoleEnum.MAIN_EXECUTORID.getValue()) {
						if (topic.getExecutorId().equals(userInfo.getLabMemberId())) {
							vo.setIsOperatePlan(BoolEnum.TRUE.getValue());
						}
					} else {
						vo.setIsOperatePlan(BoolEnum.TRUE.getValue());
					}
				}
			}

			vo.setExperimentId(experimentId);
			vo.setIsAddGroup(experiment.getIsAddGroup());
			vo.setIsAddAnalyze(experiment.getIsAddAnalyze());
			vo.setIsAddTrouble(experiment.getIsAddTrouble());
			if (userInfo.getLabMemberId().equals(topic.getExecutorId())
					|| userInfo.getLabMemberId().equals(vo.getExecutorId())) {
				vo.setOperateType(1);
				if (vo.getIsDelete().equals(IsDeleteEnum.NULLIFY.getValue())) {
					vo.setOperateType(3);
				} else if (BoolEnum.TRUE.getValue().equals(vo.getIsCheck())) {
					List<Experiment> experimentList = experimentService
							.getExperimentList(experiment.getTopicExperimentId(), null);
					List<Long> experimentIds = experimentList.stream().filter(p -> p.getId() != null)
							.map(Experiment::getId).collect(Collectors.toList());
					int count = fileManageService.selectCount(
							Arrays.asList(OssFileEnum.AnalyzeDataFile.getKey(), OssFileEnum.PrimaryDataFile.getKey()),
							experimentIds);
					vo.setOperateType(count == 0 ? 1 : 2);
				}
			}

			return setExperimentVoList(userInfo.getLabMemberId(), Arrays.asList(vo), vo.getTargetGroupId()).get(0);
		}
		return null;
	}

	public void experExecutorEdit(Long topicExperimentId, Long executorId) {
		TopicExperiment target = topicExperimentService.selectById(topicExperimentId);
		if (!target.getExecutorId().equals(executorId)) {
			Experiment experiment = experimentService.selectById(target.getExperimentId());
			Assert.isTrue(!experiment.getState().equals(ExperimentStateEnum.UNDER_WAY.getValue()), "实验进行中不能切换执行人");
			TopicExperiment topicExperiment = new TopicExperiment();
			topicExperiment.setId(topicExperimentId);
			topicExperiment.setExecutorId(executorId);
			topicExperimentService.updateById(topicExperiment);

			experiment.setExecutorId(executorId);
			experimentService.updateById(experiment);

			planService.deleteByExperimentId(target.getExperimentId());
		}

	}

	public List<ExperimentMethodListVo> getMethodList(Long topicTargetId, Long methodTypeId, Boolean exportCountAsc,
			Boolean successRateAsc) {
		List<ExperimentMethodListVo> voList = new ArrayList<>();
		TopicTarget topicTarget = topicTargetService.selectById(topicTargetId);
		Assert.notNull(topicTarget, "课题目标不存在!");
		Topic topic = topicService.selectById(topicTarget.getTopicId());
		Assert.notNull(topic, "课题不存在!");
		List<TopicExperiment> experiments = topicExperimentService.getTopicExperimentList(topicTargetId);
		List<Long> methodIds = experiments.stream().map(TopicExperiment::getMethodId).distinct()
				.collect(Collectors.toList());
		LabMember labMember = labMemberService.selectById(topic.getExecutorId());
		Assert.notNull(labMember, "主执行人不存在!");
		List<MethodTypeHide> methodTypeHides = methodTypeHideService.selectListByUserId(topic.getExecutorId());
		List<Long> hideMethodTypeIds = methodTypeHides.stream().map(MethodTypeHide::getMethodTypeId).distinct()
				.collect(Collectors.toList());
		List<Method> methodList = methodService
				.getMethodListByUserIdAndState(labMember.getUserId(), BoolEnum.FALSE, BoolEnum.TRUE, true).stream()
				.filter(e -> e.getMethodTypeId().equals(methodTypeId))
				.filter(e -> !hideMethodTypeIds.contains(e.getMethodTypeId())).collect(Collectors.toList());
		if (!CollectionUtils.isEmpty(methodList)) {
			MethodType methodType = methodTypeService.getMethodTypeById(methodTypeId);
			for (Method method : methodList) {
				ExperimentMethodListVo vo = new ExperimentMethodListVo();
				vo.setMethodId(method.getId());
				vo.setMethodTypeId(method.getMethodTypeId());
				vo.setFirstTypeId(methodType.getFirstId());
				vo.setName(method.getName());
				vo.setExportCount(method.getExportCount());
				vo.setHasVersions(method.getVersion() > 0);
				vo.setHasUsed(methodIds.contains(method.getId()));
				if (method.getSuccessCount() != null && method.getExportCount() != null
						&& method.getExportCount() > 0) {
					vo.setSuccessRate(BigDecimal.valueOf(method.getSuccessCount())
							.divide(BigDecimal.valueOf(method.getExportCount()), 4, RoundingMode.HALF_UP));
				} else {
					vo.setSuccessRate(BigDecimal.ZERO);
				}
				voList.add(vo);
			}
		}

		// 排序
		return sortExperimentMethodListVos(exportCountAsc, successRateAsc, voList);

	}

	private List<ExperimentMethodListVo> sortExperimentMethodListVos(Boolean exportCountAsc, Boolean successRateAsc,
			List<ExperimentMethodListVo> voList) {
		if (exportCountAsc == null && successRateAsc == null) {
			voList = voList.stream().sorted(Comparator.comparing(ExperimentMethodListVo::getExportCount))
					.collect(Collectors.toList());
			return voList;
		} else if (exportCountAsc != null && exportCountAsc) {
			voList = voList.stream().sorted(Comparator.comparing(ExperimentMethodListVo::getExportCount))
					.collect(Collectors.toList());
			return voList;
		} else if (exportCountAsc != null) {
			voList = voList.stream().sorted((e1, e2) -> {
				if ((e1.getExportCount() - e2.getExportCount()) > 0)
					return -1;
				if ((e1.getExportCount() - e2.getExportCount()) == 0)
					return 0;
				if ((e1.getExportCount() - e2.getExportCount()) < 0)
					return 1;
				return 0;
			}).collect(Collectors.toList());
			return voList;
		}

		if (successRateAsc) {
			voList = voList.stream().sorted(Comparator.comparing(ExperimentMethodListVo::getSuccessRate))
					.collect(Collectors.toList());
			return voList;
		} else {
			voList = voList.stream().sorted((e1, e2) -> {
				if ((e1.getSuccessRate().subtract(e2.getSuccessRate())).compareTo(BigDecimal.ZERO) > 0)
					return -1;
				if ((e1.getSuccessRate().subtract(e2.getSuccessRate())).compareTo(BigDecimal.ZERO) == 0)
					return 0;
				if ((e1.getSuccessRate().subtract(e2.getSuccessRate())).compareTo(BigDecimal.ZERO) < 0)
					return 1;
				return 0;
			}).collect(Collectors.toList());
			return voList;
		}
	}

	/**
	 * 方法详情
	 * 
	 * @author WuMenghao
	 * @param topicTargetId
	 * @param kitId
	 */
	public MethodDetail getReagentMethodDetail(Long topicTargetId, Long kitId, boolean isGlobal) {
		TopicTarget topicTarget = topicTargetService.selectById(topicTargetId);
		Assert.notNull(topicTarget, "课题目标不存在!");
		Topic topic = topicService.selectById(topicTarget.getTopicId());
		Assert.notNull(topic, "课题不存在!");
		LabMember labMember = labMemberService.selectById(topic.getExecutorId());
		Assert.notNull(labMember, "主执行人不存在!");
		MethodDetail methodDetail;
		if (isGlobal) {
			GlobalKit globalKit = globalKitService.selectById(kitId);
			Assert.notNull(globalKit, "试剂不存在!");
			methodDetail = methodLogic.getMethodDetail(globalKit.getRelateMethodId(), BoolEnum.FALSE,
					labMember.getLabId());
		} else {
			Kit kit = kitService.selectById(kitId);
			Assert.notNull(kit, "试剂不存在!");
			methodDetail = methodLogic.getMethodDetail(kit.getRelateMethodId(), BoolEnum.FALSE, labMember.getLabId());
		}
		return methodDetail;
	}

	/**
	 * 根据实验室成员查找所有课题实验Id
	 *
	 * @param labId
	 * @param labMemberId
	 * @return
	 */
	public List<Long> getMyProjectExperimentIds(Long labId, Long labMemberId) {
		List<Long> topicIds = topicMemberService.selectTopicIds(labId, labMemberId);
		List<Long> experimentIds = experimentService.selectIdByTopicIds(topicIds);
		return experimentIds;
	}

	/**
	 * 获取成员上级
	 *
	 * @param labId
	 * @param labMemberId
	 * @return
	 */
	public MemberInfoVo getMemberSuperior(Long labId, Long labMemberId) {
		Long superiorId = null;
		TeamMemberVo leader = teamLogic.getLeaderOfTeamMember(labId, labMemberId);
		if (leader != null && !leader.getLabMemberId().equals(labMemberId)) {
			superiorId = leader.getLabMemberId();
		}
		if (superiorId == null) {
			LabMember owner = labMemberService.getOwner(labId);
			superiorId = owner.getId();
		}
		return labMemberService.selectMemberVoListByIds(Arrays.asList(superiorId)).get(0);
	}

	public TopicDirectionsVo selectPageVo(Integer pageNum, Integer pageSize, Long topicId, UserInfoVo userInfo) {
		Topic topic = topicService.selectById(topicId);
		List<TopicDirectionListVo> listVos = new ArrayList<TopicDirectionListVo>();
		PageVo<TopicDirection> poPage = topicDirectionService.selectPage(pageNum, pageSize, topicId,
				userInfo.getLabId());
		List<TopicDirection> topicDirections = poPage.getContent();
		if (CollectionUtils.isNotEmpty(topicDirections)) {
			boolean isPower = this.topicEditPower(topic, userInfo);
			listVos = topicDirections.stream().map(e -> {
				TopicDirectionListVo topicDirectionListVo = new TopicDirectionListVo();
				topicDirectionListVo.setTopicDirectionId(e.getId());
				topicDirectionListVo.setTopicId(e.getTopicId());
				topicDirectionListVo.setFigure(e.getFigure());
				topicDirectionListVo.setName(e.getName());
				topicDirectionListVo.setIsEditPower(isPower ? 1 : 0);
				topicDirectionListVo.setTopicState(topic.getState());
				topicDirectionListVo.setTopicName(topic.getName());
				return topicDirectionListVo;
			}).collect(Collectors.toList());
		}
		PageVo<TopicDirectionListVo> page = new PageVo<>(poPage.getPageNum(), poPage.getPageSize(),
				poPage.getTotalRow(), listVos);

		TopicDirectionsVo vo = new TopicDirectionsVo();
		vo.setTopicId(topic.getId());
		vo.setTopicName(topic.getName());
		vo.setTopicState(topic.getState());
		vo.setPage(page);
		return vo;
	}

	/**
	 * 课题回收站列表
	 *
	 * @param userInfo
	 * @return
	 */
	public List<TopicRecycleBinVo> recycleBinList(UserInfoVo userInfo) {
		List<TopicRecycleBinVo> voList = new ArrayList<>();
		List<Long> memberIds = new ArrayList<Long>();
		if (!userInfo.getIsOwner()) {
			if (userInfo.getIsTeamLeader() == 1) {
				TeamMember teamMember = teamMemberService.selectOneByLabIdAndLabMemberId(userInfo.getLabId(),
						userInfo.getLabMemberId());
				List<TeamMember> teamList = teamMemberService.selectListByTeamIdAndState(teamMember.getTeamId(),
						TeamMemberStateEnum.IN.getState());
				memberIds = teamList.stream().map(TeamMember::getLabMemberId).collect(Collectors.toList());
			}
		}
		memberIds.add(userInfo.getLabMemberId());
		List<Topic> list = topicService.recycleBinList(userInfo.getLabId(), memberIds);
		List<Long> executorIds = list.stream().map(Topic::getExecutorId).distinct().collect(Collectors.toList());

		List<MemberInfoVo> executors = labMemberService.selectMemberVoListByIds(executorIds);
		if (!CollectionUtils.isEmpty(list)) {
			list.forEach(topic -> {
				Map<Long, List<MemberInfoVo>> map = executors.stream()
						.collect(Collectors.groupingBy(MemberInfoVo::getLabMemberId));
				map.get(topic.getExecutorId());
				TopicRecycleBinVo vo = new TopicRecycleBinVo();
				vo.setId(topic.getId());
				vo.setExecutorId(topic.getExecutorId());
				if (map.get(topic.getExecutorId()) != null) {
					vo.setExecutorName(map.get(topic.getExecutorId()).get(0).getUserName());
					vo.setImageUrl(map.get(topic.getExecutorId()).get(0).getImageUrl());
				}
				vo.setLabId(topic.getLabId());
				vo.setName(topic.getName());
				vo.setStateName(TopicStateEnum.getKey(topic.getState()));
				vo.setState(topic.getState());
				vo.setDeleteTime(topic.getUpdateTime());
				voList.add(vo);
			});
		}
		return voList;
	}

	/**
	 * 根据实验ID集合获取vo列表
	 * 
	 * @param experimentIds
	 * @return
	 */
	public List<TopicExperimentVo> getExperimentGuideList(Long labMemberId, List<Long> experimentIds) {
		List<TopicExperimentVo> experimentVoList = topicExperimentService.getExperimentGuideList(experimentIds);
		if (CollectionUtils.isNotEmpty(experimentVoList)) {

			List<ExperimentIconListVo> listVo = experimentService.getExperimentIconVoList(experimentIds);
			Map<Long, List<ExperimentIconListVo>> iconMap = listVo.stream()
					.collect(Collectors.groupingBy(ExperimentIconListVo::getExperimentId));
			List<ExperimentRelation> relationList = experimentRelationService.getRelationList(experimentIds);
			Map<Long, List<ExperimentRelation>> relationMap = relationList.stream()
					.collect(Collectors.groupingBy(ExperimentRelation::getExperimentId));
			for (TopicExperimentVo experimentVo : experimentVoList) {
				int commentNum = commentsService.getCommentNum(CommentsClassifyEnum.EXPERIMENT.getValue(),
						experimentVo.getExperimentId(), null);
				experimentVo.setCommentNum(commentNum);
				experimentVo.setRelationList(relationMap.get(experimentVo.getExperimentId()));
				ExperimentIconListVo iconVo = iconMap.get(experimentVo.getExperimentId()).get(0);
				experimentVo.setIconList(this.getExperimentIcon(labMemberId, iconVo, experimentVo));

				if (BoolEnum.TRUE.getValue().equals(experimentVo.getIsCheck())) {
					int primaryDataNum = fileManageService.selectCount(
							Arrays.asList(OssFileEnum.PrimaryDataFile.getKey()),
							Arrays.asList(experimentVo.getExperimentId()));
					if (primaryDataNum > 0) {
						experimentVo.setIsPrimaryData(BoolEnum.TRUE.getValue());
					}

					List<FileManage> compressAnalysisFile = fileManageService
							.selectList(OssFileEnum.AnalyzeDataFileThumbnail, experimentVo.getExperimentId());
					if (CollectionUtils.isNotEmpty(compressAnalysisFile)) {
						experimentVo.setCompressAnalysisFile(compressAnalysisFile.get(0));
					}
				} else {
					PageVo<ExperimentProduce> pageVo = experimentProduceService
							.produceList(experimentVo.getExperimentId(), 1, 3);
					if (pageVo != null && CollectionUtils.isNotEmpty(pageVo.getContent())) {
						List<ProduceVo> produceList = Lists.newArrayList();
						for (ExperimentProduce produce : pageVo.getContent()) {
							produceList.add(new ProduceVo(produce.getReagentTypeId(), produce.getName()));
						}
						experimentVo.setProduceList(produceList);
					}
				}

				Plan plan = planService.getPlanByExperimentId(experimentVo.getExperimentId());
				if (plan != null) {
					experimentVo.setTargetGroupId(plan.getTargetGroupId());
					experimentVo.setExperimentGroupId(plan.getExperimentGroupId());
					experimentVo.setPlanId(plan.getId());
				} else {
					experimentVo.setPlanId(0L);
				}

				ExperimentDateListVo dateVo = new ExperimentDateListVo();
				dateVo.setTopicExperimentId(experimentVo.getTopicExperimentId());
				dateVo.setExperimentId(experimentVo.getExperimentId());
				dateVo.setState(experimentVo.getState());
				dateVo.setStartTime(experimentVo.getStartTime());
				experimentVo.setExperimentList(Arrays.asList(dateVo));

			}
		}
		return experimentVoList;
	}

	/**
	 * 添加历史数据
	 *
	 * @return
	 */
	public List<TopicExperimentVo> addHistoryData(UserInfoVo userInfo, Long topicTargetId) {
		PlanTargetGroup targetGroup = this.addPlanTargetGroup(userInfo, topicTargetId);
		TopicExperimentsVo experimentsVo = this.getExperimentList(userInfo, topicTargetId, targetGroup.getId());
		return experimentsVo.getVoList();
	}

	/**
	 * 取消添加历史数据
	 *
	 * @return
	 */
	public void cancelHistoryData(UserInfoVo userInfo, Long topicTargetId) {
		PlanTargetGroup targetGroup = planTargetGroupService.getNewestPlanTargetGroup(topicTargetId);
		if (targetGroup != null && TopicStateEnum.UNDER_WAY.getValue().equals(targetGroup.getState())
				&& BoolEnum.TRUE.getValue().equals(targetGroup.getIsHistory())) {
			planTargetGroupService.deleteById(targetGroup.getId());
			planExperimentGroupService.deleteByTargetGroupId(targetGroup.getId());
			planService.deleteByTargetGroupId(targetGroup.getId());
			List<TopicExperiment> topicExperimentList = topicExperimentService.getTopicExperimentList(topicTargetId);
			if (CollectionUtils.isNotEmpty(topicExperimentList)) {
				List<Long> experimentIds = topicExperimentList.stream().map(TopicExperiment::getExperimentId)
						.collect(Collectors.toList());
				experimentService.deleteByIds(experimentIds);
				for (TopicExperiment topicExperiment : topicExperimentList) {
					Experiment latestExp = experimentService.getLatestExperiment(topicExperiment.getId());
					if (latestExp != null) {
						topicExperiment.setExperimentId(latestExp.getId());
						topicExperimentService.updateById(topicExperiment);
					} else {
						experimentService.experimentAdd(topicExperiment);
					}
				}
			}
		}
	}

	/**
	 * 结束添加历史数据
	 *
	 * @return
	 */
	public void endHistoryData(UserInfoVo userInfo, Long topicTargetId) {
		PlanTargetGroup targetGroup = planTargetGroupService.getNewestPlanTargetGroup(topicTargetId);
		if (targetGroup != null && TopicStateEnum.UNDER_WAY.getValue().equals(targetGroup.getState())
				&& BoolEnum.TRUE.getValue().equals(targetGroup.getIsHistory())) {
			targetGroup.setState(TopicStateEnum.COMPLETE.getValue());
			planTargetGroupService.updateById(targetGroup);

			List<TopicExperiment> topicExperimentList = topicExperimentService.getTopicExperimentList(topicTargetId);
			for (TopicExperiment topicExperiment : topicExperimentList) {
				experimentService.endExperiment(topicExperiment.getExperimentId(), null);
			}
		}
	}

	private PlanTargetGroup addPlanTargetGroup(UserInfoVo userInfo, Long topicTargetId) {
		TopicTarget target = topicTargetService.selectById(topicTargetId);
		Assert.notNull(target, "实验流不存在");

		boolean isAddPlan = planService.isAddPlan(topicTargetId);
		Assert.isTrue(isAddPlan, "实验流已经在计划中不能重复添加");

		List<TopicExperiment> topicExperimentList = topicExperimentService.getTopicExperimentList(topicTargetId);
		Assert.isTrue(topicExperimentList.size() > 0, "研究方向下没有正常状态实验目标");

		PlanTargetGroup targetGroup = planTargetGroupService.getNewestPlanTargetGroup(topicTargetId);
		if (targetGroup != null) {
			planTargetGroupService.endTargetGroup(targetGroup.getId());
		}

		Date planTime = DateUtil.addDate(new Date(), -365);

		targetGroup = new PlanTargetGroup();
		targetGroup.setPlanTime(planTime);
		targetGroup.setTopicId(target.getTopicId());
		targetGroup.setTopicDirectionId(target.getTopicDirectionId());
		targetGroup.setTopicTargetId(target.getId());
		targetGroup.setState(TopicStateEnum.UNDER_WAY.getValue());
		targetGroup.setIsHistory(BoolEnum.TRUE.getValue());
		targetGroup = planTargetGroupService.insert(targetGroup);

		for (TopicExperiment topicExperiment : topicExperimentList) {
			PlanExperimentGroup experimentGroup = new PlanExperimentGroup();
			experimentGroup.setTargetGroupId(targetGroup.getId());
			experimentGroup.setTopicExperimentId(topicExperiment.getId());
			experimentGroup = planExperimentGroupService.insert(experimentGroup);

			topicExperiment.setExecutorId(userInfo.getLabMemberId());
			Experiment experiment = experimentService.selectById(topicExperiment.getExperimentId());
			if (experiment.getState().equals(ExperimentStateEnum.COMPLETE.getValue())) {
				experiment = experimentService.experimentAdd(topicExperiment);
				topicExperiment.setExperimentId(experiment.getId());
			}

			planLogic.savePlan(topicExperiment, targetGroup.getId(), experimentGroup.getId(), planTime,
					userInfo.getLabId(), userInfo.getLabMemberId());
			planTime = DateUtil.addHour(planTime, 1);
		}
		return targetGroup;
	}

	/**
	 * 根据ID和类型获取名称
	 * 
	 * @param id
	 * @param type 类型：1课题，2研究内容，3实验流，4实验目标
	 * @return
	 */
	public TopicNameVo getName(Long id, Integer type) {
		TopicNameVo vo = new TopicNameVo();
		vo.setId(id);
		vo.setType(type);
		if (type == 1) {
			Topic topic = topicService.selectById(id);
			vo.setName(topic.getName());
		} else if (type == 2) {
			TopicDirection direction = topicDirectionService.getById(id);
			vo.setName(direction.getName());
		} else if (type == 3) {
			TopicTarget target = topicTargetService.selectById(id);
			vo.setName(target.getName());
		} else if (type == 4) {
			TopicExperiment experiment = topicExperimentService.selectById(id);
			vo.setName(experiment.getMethodTypeName());
		}
		return vo;
	}

	/**
	 * 查询方法历史版本
	 * 
	 * @param methodId
	 * @param userInfo
	 * @return
	 */
	public List<MethodVersionListItem> getMethodVersionList(Long methodId, UserInfoVo userInfo, Long topicTargetId) {
		// 方法
		Method thisMethod = methodService.getById(methodId);
		Assert.notNull(thisMethod, "方法不存在!");
		// 课题
		TopicTarget topicTarget = topicTargetService.selectById(topicTargetId);
		Assert.notNull(topicTarget, "课题目标不存在!");
		Topic topic = topicService.selectById(topicTarget.getTopicId());
		Assert.notNull(topic, "课题不存在!");
		List<TopicExperiment> experiments = topicExperimentService.getTopicExperimentList(topicTargetId);
		List<Long> methodIds = experiments.stream().map(TopicExperiment::getMethodId).distinct()
				.collect(Collectors.toList());
		List<MethodVersionListItem> methodVersionListItems = methodLogic.listVersionList(methodId, userInfo);

		if (!CollectionUtils.isEmpty(methodVersionListItems)) {
			for (MethodVersionListItem method : methodVersionListItems) {
				method.setHasUsed(methodIds.contains(method.getMethodId()));
			}
		}
		return methodVersionListItems;
	}
}
